//based on pocketnes code
//http://www.pocketnes.org/
//based on Jeff Frohwein's slave boot demo:
//http://www.devrs.com/gba/files/mbclient.txt

#include <stdio.h>
#include <string.h>
#include <gba.h>

extern unsigned int _start;
extern unsigned int _end;

unsigned int start_ = (int)&_start;
unsigned int end_ = (int)&_end;

void DelayCycles (u32 cycles);

int xfer(u32 send) {
	int i;
	REG_SIOMLT_SEND = send;
	DelayCycles(600);
	REG_SIOCNT = 0x2083;
	i=0x2000;
	while(--i>=0 && (REG_SIOCNT&0x80));
	return (REG_SIOMULTI1|i&0x80000000);	//return negative on timeout
}

int SendMBImageToClient() {
	MultiBootParam mp;
	u8 palette;
	int i,j;
	u8 key;
	u16 *p;
	u16 slaves;
	u16 ie;

	printf("start: 0x%X\n", start_);
	printf("end: 0x%X\n", end_);

	memset(&mp, 0, sizeof(mp));

	i=50;
	REG_RCNT=0;			//multi-comms
	do {
		j=xfer(0x6200);
	} while(--i && (j&0xfff0)!=0x7200);
	if(!i) return -1;

	slaves=(j&0xe);

	xfer(0x6100 + slaves);
	p=(u16*)0x2000000;
	for(i=0;i<96; i++) {		//send header
		xfer(*p);
		p++;
	}

	xfer(0x6200);
	xfer(0x6200 + slaves);
	mp.client_bit = slaves;
	mp.probe_count = 0xd1;
	mp.boot_srcp = (u8*)(start_+0xC0);
	i = end_ - start_+0xC0;
	i = (i+15)&~15;		//16 byte units
	mp.boot_endp = (u8*)(start_+0xC0+i);

//8x=purple->blue
//9x=blue->emerald
//ax=emerald->green
//bx=green->yellow
//cx=yellow->red
//dx=red->purple
//ex=purple->white
	palette = 0xef;
	mp.palette_data = palette;

	xfer(0x6300+palette);
	xfer(0x6300+palette);
	key=0x11;
	key+=mp.client_data[0]=REG_SIOMULTI1&0xff;
	key+=mp.client_data[1]=REG_SIOMULTI2&0xff;
	key+=mp.client_data[2]=REG_SIOMULTI3&0xff;
	mp.handshake_data = key;
	xfer(0x6400 | key);

	ie=REG_IE;
	REG_IE=0;		//don't interrupt
	REG_DMA0CNT=0;		//DMA stop
	REG_DMA1CNT=0;
	REG_DMA2CNT=0;
	REG_DMA3CNT=0;

	int result = MultiBoot(&mp, 1);
	REG_IE=ie;
	return result;
}
